Un buen ejemplo de un programa que requiere de una iteración es determinar si un número es primo. Para determinar si un número es primo, hay que ir pasando por todos sus potenciales divisores y comprobar si lo dividen o no. Por ejemplo, si tenemos el 17, probaremos el 2, el 3, el 4, etc. intentando encontrar un divisor. Si lo encontramos, de hecho, el número no es primo. Si no encontramos, será primo, ya que esa es la definición: es primo aquél número que solo tiene como divisores 1 o él mismo.
Al hacer el programa, solamente hay que tener cuidado de considerar los divisores desde el 2 hasta uno menos que el número en cuestión, que es donde se encuentran los potenciales divisores, y de alguna manera recordar si hemos visto algun divisor o no.
Las 2 primeras instrucciones del programa declaran una variable N y leen el número. Este N es el número que queremos saber si es primo:
int N; cin >> N;
Seguidamente, declararemos una variable d que contendrá el divisor que estamos considerando y la inicializaremos a 2:
int d = 2;
Aquí es donde comienza el bucle. Hay que recorrer todos los divisores e ir comprobando cada uno. Para recordar si hemos visto alguno que era divisor tendremos la variable primo, que pondremos al valor true al principio:
bool primo = true;
Durante el bucle, si vemos que algun valor de d divide a N pondremos el valor false en la variable primo y al acabar el bucle podremos saber cuál ha sido el resultado.
El bucle es este:
while (d < N) { if (N % d == 0) { primo = false; } d++; }
La expresión N % d == 0 es cierta cuando N es divisible por d (lo cual indica que no es primo). Esa expresión es la que se comprueba para cada d y en caso de ser cierta, la variable primo pasa a ser false.
Al final del bucle, si no hemos entrado en ningun caso en el if, la variable primo aún valdrá true, ya que la hemos inicializado con ese valor.
La estrategia es entonces, suponer que el número es primo e intentar buscar un "contraejemplo", es decir buscar un divisor pasando por todos los posibles a ver si alguno nos hace cambiar de opinión.
El programa entero hasta aquí es:
#include <iostream> using namespace std; int main() { int N; cin >> N; int d = 2; bool primo = true; while (d < N) { if (N % d == 0) { primo = false; } d++; } if (primo) { cout << "primo" << endl; } }
De todas maneras, si analizamos lo que sucede con un número como el 10000 veremos que el programa hace mucho trabajo en vano. La razón es que en el caso del 10000 (y todos los números pares, de hecho), nada más empezar el bucle, con d siendo 2, se descubre que el número no es primo y se pone la variable a false.
En ese momento, de hecho ya se podría salir del bucle: para qué hay que comprobar el 3, el 4, el 5, el 6 y así hasta el 9999 cuando acabamos de ver que el número no es primo?
La forma de ahorrar todos esos cálculos innecesarios es poner algo en la condición del while que haga que se salga del bucle cuando hayamos visto que el número no es primo. En realidad es tan fácil como poner:
while (d < N && primo) { if (N % d == 0) { primo = false; } d++; }
Hemos añadido && primo a la expresión del bucle para decir que solamente queremos continuar en el bucle si primo es aún cierto. Si es falso, el && produce un resultado total falso y se sale del bucle. Con este pequeño cambio, el programa solo recorre todos los divisores si es necesario.
De hecho, aún queda otra optimización más fuerte, pero tiene una razón matemática detrás, y esta se deja como ejercicio. La gran pregunta es: si un número no es primo, cuál es el divisor más grande que hay que comprobar?
La solución a la pregunta no es fácil (aunque tampoco difícil, pero hay que pensar un poco). De todas maneras, es fácil ver que si un número es divisible por 2, el "otro" divisor es la mitad del número. Es decir, que se puede afirmar con seguridad que los divisores potenciales de un número (que no sean 1 o él mismo) no pueden estar por encima de N/2. Y en cambio nosotros hemos comprobado los divisores hasta 1 menos que N...
Puedes encontrar, partiendo de N, la cota superior donde debería estar un divisor de N, cuando N no es primo?
Haz un programa que factoriza un número, es decir, muestra una lista de los factores primos de ese número (multiplicados todos juntos dan el número inicial). Si entramos el 30, por ejemplo, por pantalla sale:
2 3 5
y si ponemos el 100, sale:
2 2 5 5
Haz un programa que muestra los primeros 100 números primos.
En preparación